package org.base.admin.config;


import org.base.admin.common.exception.AuthenticationException;
import org.base.common.R;
import org.base.common.ResponseCode;
import org.base.common.SysException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.boot.context.properties.bind.BindException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;

@ControllerAdvice
public class GlobalExceptionHandler {
	
	public static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public R httpRequsetMethodNotSupported(HttpRequestMethodNotSupportedException ex){
        return R.error(HttpStatus.METHOD_NOT_ALLOWED.value(), ex.getMessage());
    }
    
    @ExceptionHandler({HttpMediaTypeNotSupportedException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    public R httpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex){
        return R.error(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(), ex.getMessage());
    }
    
    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
    public R httpMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException ex){
        return R.error(HttpStatus.NOT_ACCEPTABLE.value(), ex.getMessage());
    }
    
    @ExceptionHandler({MissingPathVariableException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
    public R missingPathVariable(MissingPathVariableException ex){
        return R.error(HttpStatus.NOT_ACCEPTABLE.value(), ex.getMessage());
    }
    
    @ExceptionHandler({MissingServletRequestParameterException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R missingServletRequestParameter(MissingServletRequestParameterException ex){
        return R.error(HttpStatus.BAD_REQUEST.value(),ex.getMessage());
    }
    
    @ExceptionHandler({ServletRequestBindingException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R servletRequestBinding(ServletRequestBindingException ex){
        return R.error(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
    }
    
    @ExceptionHandler({ConversionNotSupportedException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R conversionNotSupported(ConversionNotSupportedException ex){
        return R.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getMessage());
    }
    
    @ExceptionHandler({TypeMismatchException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R typeMismatchException(TypeMismatchException ex){
        return R.error(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
    }
    
    @ExceptionHandler({HttpMessageNotReadableException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R httpMessageNotReadable(HttpMessageNotReadableException ex){
        return R.error(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
    }
    
    
    @ExceptionHandler({HttpMessageNotWritableException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R httpMessageNotWritableException(HttpMessageNotWritableException ex){
        return R.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getMessage());
    }
    
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R methodArgumentNotValid(MethodArgumentNotValidException ex){
        return R.error(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
    }
    
    @ExceptionHandler({MissingServletRequestPartException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R missingServletRequestPart(MissingServletRequestPartException ex){
        return R.error(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
    }
    
    @ExceptionHandler({NoHandlerFoundException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public R noHandlerFound(NoHandlerFoundException ex){
        return R.error(HttpStatus.NOT_FOUND.value(), ex.getMessage());
    }
    
    @ExceptionHandler({BindException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public R missingServletRequestPart(BindException ex){
        return R.error(HttpStatus.NOT_FOUND.value(), ex.getMessage());
    }
    
    @ExceptionHandler({AsyncRequestTimeoutException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
    public R asyncRequestTimeout(AsyncRequestTimeoutException ex){
        return R.error(HttpStatus.SERVICE_UNAVAILABLE.value(),ex.getMessage());
    }
    
    @ExceptionHandler({AccessDeniedException.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public R accessDeniedException(AccessDeniedException ex) {
    	return R.error(HttpStatus.FORBIDDEN.value(), ex.getMessage());
    }
    
    @ExceptionHandler({AuthenticationException.class})
    @ResponseBody
    public R requestRRException(AuthenticationException ex){
        return new R(ResponseCode.AUTHORIZED_EXCEPTION);
    }
    
	@ExceptionHandler({SysException.class})
    @ResponseBody
    public R requestRRException(SysException ex){
        return R.error(ex.getCode(), ex.getMessage());
    }
	
	@ExceptionHandler({Exception.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R requestException(Exception ex){
		ex.printStackTrace();
		log.info(ex.getMessage());
        return R.error();
    }
	
}
